package com.hula.onion.book.server.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.hula.onion.book.server.alarm.service.ICommonAlertService;
import com.hula.onion.book.server.common.CommonResponse;
import com.hula.onion.book.server.common.LoginForm;
import com.hula.onion.book.server.common.SpiderCommon;
import com.hula.onion.book.server.config.ResponseStatusEnum;
import com.hula.onion.book.server.model.AccountInfo;
import com.hula.onion.book.server.service.AccountInfoService;
import com.hula.onion.book.server.service.AutoSyncService;
import com.hula.onion.book.server.service.PlatformInfoService;
import com.hula.onion.book.server.spider.platforms.edspay.EDSPaySpider;
import com.hula.onion.book.server.spider.platforms.jbb.JBBRSpider;
import com.hula.onion.book.server.spider.platforms.liyedai.LiYeDaiSpider;
import com.hula.onion.book.server.utils.ApplicationContextUtils;
import com.hula.onion.book.server.utils.CookieUtils;
import com.hula.onion.book.server.utils.HttpUtils;
import com.hula.onion.book.server.vo.PlatformInfoVo;
import org.apache.http.client.protocol.HttpClientContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * Description:
 * Create Date:2018/1/18 16:46
 *
 * @author liangbing
 * @version 1.0
 */
@Service
public class AutoSyncServiceImpl implements AutoSyncService {

    @Autowired
    private ApplicationContextUtils applicationContextUtils;

    @Autowired
    private AccountInfoService accountInfoService;

    @Autowired
    private PlatformInfoService platformInfoService;

    @Autowired
    private ICommonAlertService commonAlertService;

    private ThreadPoolExecutor pool = new ThreadPoolExecutor(500, 500, 2000,
            TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(1000));

    @Override
    public String doAutoSync(String userName, String password,
                             String ticket, int platformId, String userId,
                             HttpServletRequest request, HttpServletResponse response) {

        LoginForm loginForm = new LoginForm();

        loginForm.setUserName(userName);
        loginForm.setPassword(password);
        loginForm.setTicket(ticket);
        loginForm.setPlatformId(platformId);
        loginForm.setRequest(request);
        loginForm.setResponse(response);
        loginForm.setUserId(userId);

        PlatformInfoVo platformInfo = platformInfoService.getPlatformInfoById(platformId);

        String beanName = platformInfo.getSpiderName();

        if (StringUtils.isEmpty(beanName)) {
            throw new RuntimeException("请配置平台Spider Name!!!,platformId:" + platformId);
        }

        SpiderCommon spider = (SpiderCommon) applicationContextUtils.getBean(beanName);

        spider.setLoginForm(loginForm);

        CommonResponse commonResponse = spider.execute();

        if (ResponseStatusEnum.SUCCESS.getCode().equals(commonResponse.getCode())) {

            AccountInfo accountInfo = (AccountInfo) commonResponse.getData();
            accountInfoService.insertOrUpdateAccountInfo(Integer.valueOf(userId), platformId, 0, accountInfo);
        }

        //解析错误 异步发送告警信息
        if (ResponseStatusEnum.QUERY_FAIL.getCode().equals(commonResponse.getCode())
                || ResponseStatusEnum.FAIL.getCode().equals(commonResponse.getCode())) {

            final PlatformInfoVo voTemp = platformInfo;

            pool.execute(new Runnable() {
                @Override
                public void run() {

                    String title = "爬虫告警";
                    StringBuilder builder = new StringBuilder();
                    builder.append("【").append(voTemp.getName()).append("】解析投资数据异常，解析人：【").append(voTemp.getParseMan()).append("】, 请检查！");

                    commonAlertService.alarm("Error", title, builder.toString(), null);

                }
            });
        }

        return JSONObject.toJSONString(commonResponse);
    }

    @Override
    public String doManualSync(int platformId, String userId, String amount, String totalIncome, String waitIncome) {

        AccountInfo accountInfo = new AccountInfo();

        accountInfo.setAmount(new BigDecimal(amount));
        accountInfo.setTotalIntrest(new BigDecimal(totalIncome));
        accountInfo.setWaitIntrest(new BigDecimal(waitIncome));

        //insert or update
        accountInfoService.insertOrUpdateAccountInfo(Integer.parseInt(userId), platformId, 1, accountInfo);

        CommonResponse commonResponse = new CommonResponse();
        commonResponse.setData(accountInfo);

        return JSONObject.toJSONString(commonResponse);
    }

    /**
     * 执行逻辑：
     * 1.先根据平台id获取平台登陆页，请求一次平台登陆页面获取cookie。
     * 2.请求验证码页面，获取cookie（可能没有）。
     * 3.把获取到的cookie对应用户标识存缓存。
     *
     * @param platformId
     * @param userFlag
     * @param response
     * @return
     */
    @Override
    public HttpClientContext getCaptcha(int platformId, String userFlag, HttpServletResponse response) {

        PlatformInfoVo platformInfo = platformInfoService.getPlatformInfoById(platformId);

        String beanName = platformInfo.getSpiderName();

        if (StringUtils.isEmpty(beanName)) {
            throw new RuntimeException("请配置平台Spider Name!!!");
        }
        //1. 根据platformId找到对应验证码地址
        SpiderCommon spider = (SpiderCommon) applicationContextUtils.getBean(beanName);

        HttpClientContext httpClientContext = HttpClientContext.create();
        try {

            //2. 请求一次登陆页获取cookie
            String html = HttpUtils.get(spider.getLoginPageURL(), httpClientContext);

            spider.getIndexPageInfo(html, platformId, userFlag);

            // 立业贷特殊处理
            if (spider instanceof LiYeDaiSpider) {
                ((LiYeDaiSpider) spider).beforeGetImg(platformId, userFlag, httpClientContext);
            }

            if (spider instanceof JBBRSpider) {
                ((JBBRSpider) spider).beforeGetImg(httpClientContext);
            }

            //E都市钱包
            if (spider instanceof EDSPaySpider) {
                byte[] b = ((EDSPaySpider) spider).getCheckCode(httpClientContext);
                responseCode(b, platformId, userFlag, response, httpClientContext);
                return httpClientContext;
            }
            //下载验证码
            byte[] bytes = HttpUtils.downImgCode(spider.getCaptchaURL(), httpClientContext);
            responseCode(bytes, platformId, userFlag, response, httpClientContext);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return httpClientContext;
    }

    @Override
    public String doDelSyncInfo(int id) {

        CommonResponse commonResponse = new CommonResponse(ResponseStatusEnum.FAIL);

        int l = accountInfoService.delAccountInfo(id);

        if (l == 1) {
            commonResponse = new CommonResponse(ResponseStatusEnum.SUCCESS);
        }

        return JSONObject.toJSONString(commonResponse);
    }

    private void responseCode(byte[] bytes, int platformId, String userFlag, HttpServletResponse response, HttpClientContext httpClientContext) throws IOException {

        if (bytes != null) {
            //3. 缓存cookie
            CookieUtils.saveCookie(platformId, userFlag, httpClientContext.getCookieStore());
            //输出流
            ServletOutputStream responseOutputStream = response.getOutputStream();

            response.setHeader("Cache-Control", "no-store");
            response.setHeader("Pragma", "no-cache");
            response.setDateHeader("Expires", 0);
            response.setContentType("image/jpeg");

            responseOutputStream.write(bytes);
            responseOutputStream.flush();
            responseOutputStream.close();
        }

    }
}
